//
// File: CXSparseAPI.cpp
//
// MATLAB Coder version            : 5.4
// C/C++ source code generated on  : 27-Mar-2025 11:51:36
//

// Include Files
#include "CXSparseAPI.h"
#include "rt_nonfinite.h"
#include "sparse.h"
#include "coder_array.h"
#include "CXSparseSupport/cs.h"
#include "CXSparseSupport/makeCXSparseMatrix.h"
#include "CXSparseSupport/solve_from_qr.h"
#include <cstddef>
#include <cstring>

// Function Definitions
//
// Arguments    : const sparse *A
//                const sparse *b
//                int n
//                sparse *out
// Return Type  : void
//
namespace coder {
namespace internal {
void CXSparseAPI::iteratedQR(const sparse *A, const sparse *b, int n,
                             sparse *out)
{
  cs_di *cxA;
  cs_din *N;
  cs_dis *S;
  b_sparse s;
  sparse in;
  array<double, 1U> outBuff;
  array<signed char, 2U> r;
  double tol;
  int b_loop_ub;
  int b_n;
  int i;
  int loop_ub;
  int numalloc;
  int unnamed_idx_0;
  boolean_T p;
  if (A->m < A->n) {
    A->ctranspose(&in);
    cxA = makeCXSparseMatrix(in.colidx[in.colidx.size(0) - 1] - 1, in.n, in.m,
                             &(in.colidx.data())[0], &(in.rowidx.data())[0],
                             &(in.d.data())[0]);
  } else {
    cxA = makeCXSparseMatrix(
        A->colidx[A->colidx.size(0) - 1] - 1, A->n, A->m,
        &(((::coder::array<int, 1U> *)&A->colidx)->data())[0],
        &(((::coder::array<int, 1U> *)&A->rowidx)->data())[0],
        &(((::coder::array<double, 1U> *)&A->d)->data())[0]);
  }
  S = cs_di_sqr(2, cxA, 1);
  N = cs_di_qr(cxA, S);
  cs_di_spfree(cxA);
  qr_rank_di(N, &tol);
  out->m = n;
  out->n = b->n;
  out->d.set_size(1);
  out->d[0] = 0.0;
  out->maxnz = 1;
  out->colidx.set_size(b->n + 1);
  out->colidx[0] = 1;
  out->rowidx.set_size(1);
  out->rowidx[0] = 0;
  i = b->n;
  for (numalloc = 0; numalloc < i; numalloc++) {
    out->colidx[numalloc + 1] = 1;
  }
  out->fillIn();
  if (b->m < n) {
    outBuff.set_size(n);
  } else {
    outBuff.set_size(b->m);
  }
  i = b->n;
  if (b->n - 1 >= 0) {
    s.colidx.set_size(2);
    unnamed_idx_0 = b->m;
    loop_ub = b->m;
    if (b->m < 1) {
      b_loop_ub = 0;
    } else {
      b_loop_ub = b->m;
    }
    if (n < 1) {
      b_n = 0;
    } else {
      b_n = n;
    }
    p = (b_n == 1);
  }
  for (int b_i{0}; b_i < i; b_i++) {
    int extraSpace;
    int i1;
    extraSpace = b->colidx[b_i + 1] - b->colidx[b_i];
    if (extraSpace >= 1) {
      numalloc = extraSpace;
    } else {
      numalloc = 1;
    }
    s.d.set_size(numalloc);
    for (i1 = 0; i1 < numalloc; i1++) {
      s.d[i1] = 0.0;
    }
    s.rowidx.set_size(numalloc);
    for (i1 = 0; i1 < numalloc; i1++) {
      s.rowidx[i1] = 0;
    }
    s.colidx[0] = 1;
    s.colidx[1] = 1;
    if (extraSpace != 0) {
      for (int k{0}; k < extraSpace; k++) {
        s.d[k] = 1.0;
        s.rowidx[k] = b->rowidx[(b->colidx[b_i] + k) - 1];
      }
      s.colidx[1] = extraSpace + 1;
    }
    r.set_size(unnamed_idx_0, 1);
    for (i1 = 0; i1 < loop_ub; i1++) {
      r[i1] = 0;
    }
    numalloc = s.colidx[1] - 1;
    i1 = s.colidx[0];
    for (extraSpace = i1; extraSpace <= numalloc; extraSpace++) {
      r[s.rowidx[extraSpace - 1] - 1] =
          static_cast<signed char>(s.d[extraSpace - 1]);
    }
    for (i1 = 0; i1 < b_loop_ub; i1++) {
      outBuff[i1] = r[i1];
    }
    solve_from_qr_di(N, S, (double *)&(outBuff.data())[0], b->m, n);
    if (p && (out->m != 1)) {
      int nzColAlloc;
      int nzColAlloc_tmp;
      int nzRhs;
      extraSpace = out->m;
      nzColAlloc_tmp = 0;
      b_n = out->colidx[out->colidx.size(0) - 1];
      nzColAlloc = out->colidx[b_i + 1] - out->colidx[b_i];
      numalloc = 0;
      nzRhs = 0;
      for (int k{0}; k < extraSpace; k++) {
        tol = outBuff[numalloc];
        numalloc++;
        if (!(tol == 0.0)) {
          nzRhs++;
        }
      }
      if (nzColAlloc < nzRhs) {
        nzColAlloc = nzRhs - nzColAlloc;
        numalloc = (out->maxnz - out->colidx[out->colidx.size(0) - 1]) + 1;
        if (numalloc < nzColAlloc) {
          sparse::b_realloc(out, (out->maxnz + nzColAlloc) - numalloc,
                            out->colidx[b_i] - 1, out->colidx[b_i + 1],
                            out->colidx[out->colidx.size(0) - 1] - 1,
                            nzColAlloc);
        } else {
          numalloc = out->colidx[b_i + 1];
          extraSpace = (numalloc + nzColAlloc) - 1;
          numalloc = out->colidx[out->colidx.size(0) - 1] - numalloc;
          if (numalloc > 0) {
            std::memmove((void *)&out->rowidx[extraSpace],
                         (void *)&out->rowidx[out->colidx[b_i + 1] - 1],
                         (unsigned int)((size_t)numalloc * sizeof(int)));
            std::memmove((void *)&out->d[extraSpace],
                         (void *)&out->d[out->colidx[b_i + 1] - 1],
                         (unsigned int)((size_t)numalloc * sizeof(double)));
          }
        }
        numalloc = out->colidx[b_i] - 1;
        i1 = out->m;
        for (int k{0}; k < i1; k++) {
          tol = outBuff[nzColAlloc_tmp];
          nzColAlloc_tmp++;
          if (tol != 0.0) {
            out->rowidx[numalloc] = k + 1;
            out->d[numalloc] = tol;
            numalloc++;
          }
        }
        i1 = b_i + 2;
        numalloc = out->n + 1;
        for (int k{i1}; k <= numalloc; k++) {
          out->colidx[k - 1] = out->colidx[k - 1] + nzColAlloc;
        }
      } else {
        int outIdx;
        outIdx = out->colidx[b_i] - 1;
        i1 = out->m;
        for (int k{0}; k < i1; k++) {
          tol = outBuff[nzColAlloc_tmp];
          nzColAlloc_tmp++;
          if (tol != 0.0) {
            out->rowidx[outIdx] = k + 1;
            out->d[outIdx] = tol;
            outIdx++;
          }
        }
        extraSpace = nzColAlloc - nzRhs;
        if (extraSpace > 0) {
          numalloc = b_n - out->colidx[b_i + 1];
          if (numalloc > 0) {
            std::memmove((void *)&out->rowidx[outIdx],
                         (void *)&out->rowidx[out->colidx[b_i + 1] - 1],
                         (unsigned int)((size_t)numalloc * sizeof(int)));
            std::memmove((void *)&out->d[outIdx],
                         (void *)&out->d[out->colidx[b_i + 1] - 1],
                         (unsigned int)((size_t)numalloc * sizeof(double)));
          }
          i1 = b_i + 2;
          numalloc = out->n + 1;
          for (int k{i1}; k <= numalloc; k++) {
            out->colidx[k - 1] = out->colidx[k - 1] - extraSpace;
          }
        }
      }
    } else {
      int nzColAlloc;
      int nzColAlloc_tmp;
      int nzRhs;
      extraSpace = out->m;
      b_n = out->colidx[out->colidx.size(0) - 1];
      nzColAlloc_tmp = out->colidx[b_i + 1];
      nzColAlloc = nzColAlloc_tmp - out->colidx[b_i];
      nzRhs = 0;
      for (int k{0}; k < extraSpace; k++) {
        if (!(outBuff[k] == 0.0)) {
          nzRhs++;
        }
      }
      if (nzColAlloc < nzRhs) {
        nzColAlloc = nzRhs - nzColAlloc;
        numalloc = (out->maxnz - out->colidx[out->colidx.size(0) - 1]) + 1;
        if (numalloc < nzColAlloc) {
          sparse::b_realloc(out, (out->maxnz + nzColAlloc) - numalloc,
                            out->colidx[b_i] - 1, out->colidx[b_i + 1],
                            out->colidx[out->colidx.size(0) - 1] - 1,
                            nzColAlloc);
        } else {
          extraSpace = (nzColAlloc_tmp + nzColAlloc) - 1;
          numalloc = out->colidx[out->colidx.size(0) - 1] - nzColAlloc_tmp;
          if (numalloc > 0) {
            std::memmove((void *)&out->rowidx[extraSpace],
                         (void *)&out->rowidx[out->colidx[b_i + 1] - 1],
                         (unsigned int)((size_t)numalloc * sizeof(int)));
            std::memmove((void *)&out->d[extraSpace],
                         (void *)&out->d[out->colidx[b_i + 1] - 1],
                         (unsigned int)((size_t)numalloc * sizeof(double)));
          }
        }
        numalloc = out->colidx[b_i] - 1;
        i1 = out->m;
        for (int k{0}; k < i1; k++) {
          if (outBuff[k] != 0.0) {
            out->rowidx[numalloc] = k + 1;
            out->d[numalloc] = outBuff[k];
            numalloc++;
          }
        }
        i1 = b_i + 2;
        numalloc = out->n + 1;
        for (int k{i1}; k <= numalloc; k++) {
          out->colidx[k - 1] = out->colidx[k - 1] + nzColAlloc;
        }
      } else {
        int outIdx;
        outIdx = out->colidx[b_i] - 1;
        i1 = out->m;
        for (int k{0}; k < i1; k++) {
          if (outBuff[k] != 0.0) {
            out->rowidx[outIdx] = k + 1;
            out->d[outIdx] = outBuff[k];
            outIdx++;
          }
        }
        extraSpace = nzColAlloc - nzRhs;
        if (extraSpace > 0) {
          numalloc = b_n - nzColAlloc_tmp;
          if (numalloc > 0) {
            std::memmove((void *)&out->rowidx[outIdx],
                         (void *)&out->rowidx[out->colidx[b_i + 1] - 1],
                         (unsigned int)((size_t)numalloc * sizeof(int)));
            std::memmove((void *)&out->d[outIdx],
                         (void *)&out->d[out->colidx[b_i + 1] - 1],
                         (unsigned int)((size_t)numalloc * sizeof(double)));
          }
          i1 = b_i + 2;
          numalloc = out->n + 1;
          for (int k{i1}; k <= numalloc; k++) {
            out->colidx[k - 1] = out->colidx[k - 1] - extraSpace;
          }
        }
      }
    }
  }
  cs_di_sfree(S);
  cs_di_nfree(N);
}

} // namespace internal
} // namespace coder

//
// File trailer for CXSparseAPI.cpp
//
// [EOF]
//
